<!--
 * @title: 自定义附件上传组件
 * @author: andy.ten@tom.com & xukaixing@hotmail.com
 * @Date: 2022-05-04 21:51:12
 * @LastEditors: andy.ten@tom.com
 * @LastEditTime: 2022-06-05 17:20:09
 * @version: 1.0.6
 * @copyright: copyright (c) 2022 andyten
 *  node: you can not copy and/or use and/or modify this program free,
 *  please reserve the segment above.Please mail me if you have any question.
-->
<template>
  <div class="ht-upload__wrapper">
    <el-upload
      v-if="listType === 'text'"
      ref="htupload"
      :action="upload"
      list-type="picture"
      :accept="accept"
      :auto-upload="autoUpload"
      :drag="drag"
      multiple
      :limit="maxFileLimit"
      :file-list="fileList"
      :headers="headers"
      :data="params"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :on-error="handleErr"
      :on-success="handleSuccess"
      :on-progress="handleProgress"
      class="ht-upload ht-upload--text"
    >
      <i class="el-icon-upload" />
      <div class="el-upload__text">将文件拖到此处，或<em>选取文件</em></div>
      <div slot="tip" class="el-upload__tip">{{ limit === 1 ? '只能上传 xlsx 、 xls 格式文件 , 且只能选择一个文件': '单个文件不超过10MB' }}</div>
      <div slot="file" slot-scope="{file}" v-loading="file.status === 'uploading'" style="position: absolute;display:contents;">
        <!-- <pdf
          v-if="file.name.endsWith('.pdf')"
          :src="getPdfUrl(file.url)"
          :page="1"
          class="ht-upload--pdf"
        /> -->
        <img
          v-if="file.name.endsWith('.jpg') || file.name.endsWith('.png') || file.name.endsWith('.jpeg')"
          class="el-upload-list__item-thumbnail"
          :src="file.url"
          alt=""
        >
        <span v-if="file.name.endsWith('.jpg') || file.name.endsWith('.png') || file.name.endsWith('.jpeg')" class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in" />
          </span>
          <span
            v-if="file.id"
            class="el-upload-list__item-download"
            @click="handleDownload(file)"
          >
            <i class="el-icon-download" />
          </span>
        </span>
        <a class="el-upload-list__item-name" @click="handleDownload(file)">
          <i v-if="!file.name.endsWith('.jpg') && !file.name.endsWith('.png') && !file.name.endsWith('.jpeg')" class="el-icon-document" />
          {{ file.name }}
        </a>
        <label class="el-upload-list__item-status-label">
          <i class="el-icon-upload-success el-icon-check" />
        </label>
        <i class="el-icon-close" @click="()=>handleRemove(file)" />
        <i class="el-icon-close-tip">按 delete 键可删除</i>
      </div>
    </el-upload>
    <el-upload
      v-else
      ref="htuploadpic"
      :action="upload"
      list-type="picture-card"
      :auto-upload="autoUpload"
      accept=".jpg, .jpeg, .png, .gif"
      multiple
      :limit="maxFileLimit"
      :file-list="fileList"
      :headers="headers"
      :data="params"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :on-error="handleErr"
      :on-success="handleSuccess"
      :on-progress="handleProgress"
      class="ht-upload"
    >
      <i slot="default" class="el-icon-plus" />
      <div slot="tip" class="el-upload__tip">只能上传jpg/png格式文件，且不超过10MB</div>
      <div slot="file" slot-scope="{file}" v-loading="file.status === 'uploading'">
        <span class="ht-upload__uploadStatus" />
        <!-- <pdf
          v-if="file.name.endsWith('.pdf')"
          :src="getPdfUrl(file.url)"
          :page="1"
        /> -->
        <img
          class="el-upload-list__item-thumbnail"
          :src="file.url"
          alt=""
        >
        <span class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in" />
          </span>
          <span
            v-if="file.id"
            class="el-upload-list__item-download"
            @click="handleDownload(file)"
          >
            <i class="el-icon-download" />
          </span>
          <span
            v-if="!disabled"
            class="el-upload-list__item-delete"
            @click="handleRemove(file)"
          >
            <i class="el-icon-delete" />
          </span>
        </span>
      </div>
    </el-upload>
    共计：{{ totalNums }} 个文件，总大小：{{ (totalSize/1024/1024).toFixed(2) }} MB
    <ht-button style="margin: 10px 22px;" type="primary" biz-type="upload" :loading="loading" @click="submitUpload">上传文件</ht-button>
    <el-dialog :visible.sync="dialogVisible">
      <!-- <pdf
        v-if="dialogIsPdf"
        width="100%"
        :src="dialogImageUrl"
        :page="1"
      /> -->
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
    <!-- <el-progress v-show="showProcess" :percentage="processLen" status="success" /> -->
  </div>
</template>

<script>
// import pdf from 'vue-pdf-signature';
// 解决中文PDF加载空白
// import CMapReaderFactory from 'vue-pdf-signature/src/CMapReaderFactory.js';
export default {
  name: 'HtUpload',
  components: {
    // pdf
  },
  props: {
    uploadType: {
      type: String,
      required: false,
      default: 'upload'
    },
    upload: {
      type: String,
      required: false,
      default: '#'
    },
    remove: {
      type: Function,
      required: false,
      default: undefined
    },
    download: {
      type: Function,
      required: false,
      default: undefined
    },
    type: {
      type: String,
      required: false,
      default: 'text'
    },
    accept: {
      type: String,
      required: false,
      default: undefined
    },
    autoUpload: {
      type: Boolean,
      required: false,
      default: false
    },
    drag: {
      type: Boolean,
      required: false,
      default: true
    },
    limit: {
      type: Number,
      required: false,
      default: 20
    },
    maxFileSize: { // 单个附件最大允许大小，单位MB
      type: Number,
      required: false,
      default: 10
    },
    headers: {
      type: Object,
      required: false,
      default: () => {}
    },
    params: {
      type: Object,
      required: false,
      default: () => {}
    },
    cb: {
      type: Function,
      required: false,
      default: undefined
    }
  },
  data() {
    return {
      listType: this.type === 'pic' ? 'picture-card' : 'text',
      dialogImageUrl: '',
      dialogIsPdf: false, // 判断弹出窗口预览是否是pdf文件
      dialogVisible: false,
      disabled: false,
      fileList: [],
      addFileHistory: [],
      current: {},
      totalSize: 0,
      totalNums: 0,
      maxFileLimit: this.limit,
      showProcess: false,
      processLen: 0,
      loading: false
    };
  },
  computed: {
  },
  created() {
    // alert(this.action);
    // alert(this.accept);
  },
  methods: {
    // getPdfUrl(url) {
    //   const pdfUrl = pdf.createLoadingTask({ url: url, CMapReaderFactory });
    //   // 加载完PDF后对缓存进行清除
    //   // for (var key in require.cache)
    //   //   if (key.indexOf('bcmap') >= 0)
    //   //     delete require.cache[key];
    //   return pdfUrl;
    // },
    /**
     * @todo: 删除附件
     * @author: andy.ten@tom.com & xukaixing@hotmail.com
     * @Date: 2022-05-21 15:47:10
     * @param {*} file
     */
    async handleRemove(file) {
      if (file.status === 'success') {
        const param = this.params;
        if (!param.fuuid) {
          param['id'] = file.id;
          param['fuuid'] = file.fuuid;
        }
        if (this.remove && param.id)
          await this.remove(param);
      }

      let index = 0;
      for (let i = 0; i < this.fileList.length; i++)
        if (this.fileList[i].name === file.name) {
          index = i;
          break;
        }
      this.fileList.splice(index, 1);

      // 总文件数
      this.totalNums--;
      // 计算总大小
      this.totalSize -= file.size;
    },
    handlePictureCardPreview(file) {
      if (file.name.endsWith('.pdf')) {
        this.dialogIsPdf = true;
        // this.dialogImageUrl = this.getPdfUrl(file.url);
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      } else {
        this.dialogIsPdf = false;
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      }
    },
    /**
     * @todo: 下载附件
     * @author: andy.ten@tom.com & xukaixing@hotmail.com
     * @Date: 2022-05-28 12:09:20
     * @param {*} file
     */
    async handleDownload(file) {
      if (!file.id) {
        this.$notify.message('请先上传附件', 'warning');
        return;
      }
      const param = this.params;
      param['id'] = file.id;
      param['fuuid'] = file.fuuid;
      param['fileName'] = file.name;
      console.log(file);
      file.status = 'uploading';
      await this.download(param).then((res) => {
        // 设置下载按钮状态
        if (res && res.data) {
          const fileName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]);
          const blob = new Blob([res.data], {
            type: 'application/octet-stream'
          });
          const url = window.URL.createObjectURL(blob);
          const link = document.createElement('a');
          link.style.display = 'none';
          link.href = url;
          link.setAttribute('download', fileName);
          document.body.appendChild(link);
          // 兼容ie
          if (!!window.ActiveXObject || 'ActiveXObject' in window)
            window.navigator.msSaveOrOpenBlob(blob, link.download);
          else
            link.click();
          link.remove();
          window.URL.revokeObjectURL(url);
          this.$notify.message('下载附件成功', 'success');
        } else
          this.$notify.alert('下载附件错误: 返回数据不正确', 'error');
      });
      file.status = 'success';
    },
    handleExceed(file, list) {
      this.$notify.message(`不能选择超过 ${this.maxFileLimit} 个文件上传`, 'warning');
    },
    /**
     * @todo: 上传错误信息（注意：先执行handleErr，然后会再执行handleChange）
     * @author: andy.ten@tom.com & xukaixing@hotmail.com
     * @Date: 2022-05-30 10:17:25
     * @param {*} errors
     * @param {*} file
     * @param {*} list
     */
    handleErr(errors, file, list) {
      if (file.status === 'fail') {
        let msg = {};
        if (typeof errors === 'object' && errors.message)
          msg = JSON.parse(errors.message);
        this.$notify.alert(`${file.name} 上传失败 [${msg.code}] - ${msg.message}`, 'error');
        const isHas = list.some((x) => {
          return x.name === file.name;
        });
        if (isHas === false) {
          list.push(file);
          file.status = 'ready';
        }
      }

      // 失败时设置uploading状态的附件显示
      // this.addFileHistory.forEach((x) => {
      //   if (x.status === 'uploading')
      //     if (!list.some((item) => {
      //       item.name === x.name;
      //     })) {
      //       x.status = 'success';
      //       this.fileList.push(x);
      //     }
      // });
    },
    handleSuccess(response, file, list) {
      if (response)
        if (response.status === 'fail') {
          this.$notify.alert(`${file.name} 上传失败 - ${response.message}`, 'error');
          if (response.code !== 23008 && response.code !== 23004)
            file.status = 'ready';
        } else {
          const { datas } = response;
          if (this.uploadType === 'import') {
            if (this.cb)
              this.cb(response, this.params);
          } else {
            file['fuuid'] = datas.fuuid;
            file['id'] = datas.id;
            if (this.cb)
              this.cb(file, this.params);
          }
        }
    },
    handleProgress(event, file, list) {
      this.showProcess = true;
    },
    /**
     * @todo: 选择文件、上传成功/上传失败方法执行后均会再次调用
     * @author: andy.ten@tom.com & xukaixing@hotmail.com
     * @Date: 2022-05-12 17:18:39
     * @param {*} file
     * @param {*} list
     */
    handleChange(file, list) {
      if (file.status === 'ready') {
        this.current = file;
        const fileSize = file.size;
        const fileName = file.name;
        let isExisted = false;
        if (list.length > 1)
          for (let i = 0; i < list.length - 1; i++)
            if (list[i].name === fileName) {
              isExisted = true;
              break;
            }
        // 校验是否存在
        if (isExisted === true) {
          this.$notify.message(`文件: ${fileName} 已存在`, 'warning');
          list.splice(list.length - 1, 1);
          return;
        }
        // 校验是否符合大小要求
        const maxFileSize = this.maxFileSize;
        if (fileSize > maxFileSize * 1024 * 1024) {
          this.$notify.message(`文件: ${fileName} 超过最大允许大小( ${maxFileSize} MB) `, 'warning');
          list.splice(list.length - 1, 1);
          return;
        }
        // 总文件数
        this.totalNums++;
        // 计算总大小
        this.totalSize += fileSize;
        this.addFileHistory.push(file);
        const isHas = this.fileList.some((x) => {
          return x.name === file.name;
        });
        if (isHas === false)
          this.fileList.push(file);
      } else if (file.status === 'fail')
        // this.fileList.push(file);
        file.status = 'fail';
      else if (file.status === 'uploading')
        file.status = 'success';

      this.loading = false;
    },
    /**
     * @todo: 上传附件
     * @author: andy.ten@tom.com & xukaixing@hotmail.com
     * @Date: 2022-05-12 18:11:12
     */
    async submitUpload() {
      if (this.fileList.filter((x) => {
        if (x.status === 'ready')
          return true;
      }).length > 0) {
        this.loading = true;
        if (this.listType === 'text')
          await this.$refs.htupload.submit();
        else
          await this.$refs.htuploadpic.submit();
      } else
        this.$notify.message('请先选择文件.', 'warning');
    }
  }
};
</script>
<style lang="scss" scoped>
.ht-upload__wrapper{
  .ht-upload{
    .el-upload-list{
      .el-upload-list__item{
        .el-upload-list__item-actions{
          i{
            font-size: 20px;
            font-weight: 400;
            color:#fff;
          }
        }
      }

      .is-success{
        .ht-upload__uploadStatus{
          position: fixed;
          display: block;
          width: 100%;
          height: 40px;
          margin-top: 106px;
          margin-left: 106px;
          line-height: 40px;
          background:url('./success.png') no-repeat;
        }

      }

      .is-fail{
        .ht-upload__uploadStatus{
          position: fixed;
          display: block;
          width: 100%;
          height: 40px;
          margin-top: 106px;
          margin-left: 106px;
          line-height: 40px;
          background:url('./fail.png') no-repeat;
        }

      }
    }

    .el-upload-list--picture{
      .el-upload-list__item{
        &>div{
          width:100%;
        }

        .el-upload-list__item-name{
          // position: absolute;

          i{
            display: block;
          }
        }

        .el-upload-list__item-actions{
          position: relative;
          float: right;
          width: 20px;
          margin: 20px 0;

          i{
            font-size: 20px;
            font-weight: 400;
            color:#000;
            cursor: pointer;
          }
        }
      }
    }
  }

  .ht-upload--pdf{
    position: absolute !important;
    margin-left:-70px;
  }

  .ht-upload--pdf + .el-upload-list__item-thumbnail{
    display: none;
  }

  .ht-upload--text{
    width: 360px;

    .el-upload-list--picture{
      .el-upload-list__item-name{
        margin: 5px;
        white-space: normal;

        i{
          font-size: 60px;
        }
      }
    }
  }

  .el-dialog__wrapper{
    ::v-deep .el-dialog{
      max-width: 650px !important;
      max-height: calc(100% - 97px);

      .el-dialog__header{
        padding: 5px;

        .el-dialog__headerbtn{
          top:2px;

          i{
            font-size: 20px;
            font-weight: 400;
            color: #000;
          }
        }
      }

      .el-dialog__body{
        max-height: calc(100% - 97px);
        padding: 10px;

        img{
          width: 99%;
          max-height: calc(100vh - 177px);
        }
      }
    }
  }

}
</style>
